package backend

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"gitee.com/openeuler/go-gitee/gitee"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"{{.ProjectName}}/backend/utils"
)

type UpdateApp struct {
	currentVersion   string
	newVersion       string
	appBinaryPath    string
	newAppBinaryPath string
	dataFolderPath   string
	app              *App
}

func (u *UpdateApp) Run() {
	var err error
	u.currentVersion = u.app.AppMeta.AppVersion
	u.newVersion = u.GetLatestRelease()
	u.newAppBinaryPath = fmt.Sprintf("%s/NewVersion/%s_%s_%s%s", u.app.AppMeta.AppDataDir, u.app.AppMeta.AppName, runtime.GOOS, runtime.GOARCH, u.app.AppMeta.AppFileExt)
	err = u.DownLoadNewVersion()
	if err != nil {
		u.app.log.Error(fmt.Sprintf("下载错误. 原因: %s", err))
	}
	u.appBinaryPath, err = os.Executable()
	u.app.log.Info(fmt.Sprintf("appBinaryPath:===> %s", u.appBinaryPath))
	if err != nil {
		u.app.log.Error(fmt.Sprintf("无法收集app二进制文件的路径. 原因: %s", err))
	}
	u.dataFolderPath = u.app.AppMeta.AppDataDir

	err = u.TriggerUpdate()
	if err != nil {
		u.app.log.Error(fmt.Sprintf("无法更新app. 原因: %s", err))
		u.app.SendError("无法更新app. 原因: ", err)
	}
}

func (u *UpdateApp) Check() (result string) {
	u.currentVersion = u.app.AppMeta.AppVersion
	u.newVersion = u.GetLatestRelease()
	return utils.VarsionDiff(u.newVersion, u.currentVersion)
}

func (u *UpdateApp) TriggerUpdate() error {
	_, fileExt := utils.GetUserOS()
	pid := os.Getpid()
	u.app.log.Info(fmt.Sprintf("pid=== : %s", pid))
	main := u.dataFolderPath + "/" + PLUGIN_UPDATE_FILENAME + fileExt
	args := []string{"-init_dag_path=" + u.dataFolderPath, "-old_app_path=" + u.appBinaryPath, "-new_app_path=" + u.newAppBinaryPath, "-app_name=" + "true", "-pid=" + strconv.Itoa(pid)}

	cmd := exec.Command(main, args...)
	u.app.log.Info(fmt.Sprintf("正在运行命令 : %s", cmd))

	var stderr bytes.Buffer
	cmd.Stderr = &stderr // Captures STDERR

	err := cmd.Run()
	if err != nil {
		errFormatted := fmt.Sprint(err) + ": " + stderr.String()
		return errors.New(errFormatted)
	}
	return nil
}

func (u *UpdateApp) GetLatestRelease() string {
	cfg := gitee.NewConfiguration()
	client := gitee.NewAPIClient(cfg)
	ctx := context.Background()
	var release gitee.Release
	release, _, err := client.RepositoriesApi.GetV5ReposOwnerRepoReleasesLatest(ctx, APP_OENER, APP_REPO, nil)
	if err != nil {
		u.app.log.Error(fmt.Sprintf("最后版本获取失败. 原因: %s", err))
	}
	return release.TagName

}

func (u *UpdateApp) DownLoadNewVersion() error {
	var options utils.DownloadOptions
	options.OnlinePath = fmt.Sprintf("%s/%s/%s_%s_%s%s", APP_DOWNLOAD_URL, u.newVersion, u.app.AppMeta.AppName, runtime.GOOS, runtime.GOARCH, u.app.AppMeta.AppFileExt)
	options.LocalPath = u.newAppBinaryPath
	options.FileName = fmt.Sprintf("%s_%s_%s%s", u.app.AppMeta.AppName, runtime.GOOS, runtime.GOARCH, u.app.AppMeta.AppFileExt)

	u.app.log.Info(fmt.Sprintf("OnlinePath:===> %s", options.OnlinePath))
	u.app.log.Info(fmt.Sprintf("LocalPath:===> %s", options.LocalPath))
	u.app.log.Info(fmt.Sprintf("FileName:===> %s", options.FileName))
	err := utils.DownloadFile(options, os.ModePerm)

	if err != nil {
		return err
	}
	return nil
}
